package com.gmall.data.service;

import com.gmall.data.api.UserActionSequenceQueryService;
import com.gmall.data.pojo.RuleAtomicParam;
import com.gmall.data.pojo.RuleParam;
import com.gmall.data.utils.ConnectionUtil;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

/**
 * 行为序列类路径匹配查询service，clickhouse实现
 */
public class UserActionSequenceQueryServiceChImpl implements UserActionSequenceQueryService {

    private Connection conn;

    public UserActionSequenceQueryServiceChImpl() {
        conn = ConnectionUtil.getChConnection();
    }

    /**
     * 从clickhouse中查询行为序列条件是否满足
     *
     * @param deviceId
     * @param ruleParam
     * @return
     * @throws Exception
     */
    @Override
    public boolean queryActionSequence(String deviceId, RuleParam ruleParam) throws Exception {

        // 获取规则中，路径模式的总步骤数
        int totalStep = ruleParam.getUserActionSequenceParams().size();
        // 规则原子条件
        RuleAtomicParam ruleAtomicParam = ruleParam.getUserActionSequenceParams().get(0);

        // 取出查询sql
        String sql = ruleParam.getActionSequenceQuerySql();
        PreparedStatement ps = conn.prepareStatement(sql);

        // 需要将sql中的deviceId占位符替换成真实deviceId
        ps.setString(1, deviceId);
        ps.setLong(2, ruleAtomicParam.getRangeStart());
        ps.setLong(3, ruleAtomicParam.getRangeEnd());
        ResultSet resultSet = ps.executeQuery();

        /* 从返回结果中进行条件判断
         * ┌─deviceId─┬─isMatch3─┬─isMatch2─┬─isMatch1─┐
         * │ 000001   │       0  │        0 │        1 │
         * └──────────┴──────────┴──────────┴──────────┘
         * 重要逻辑： 查询结果中有几个1，就意味着最大完成步骤是几！！！
         */
        int maxStep = 0;
        while (resultSet.next()) {   // 返回结果最多就1行，这个while就走一次!!!
            // 对一行结果中的1进行累加，累加结果即完成的最大步骤数
            for (int i = 2; i < totalStep + 2; i++) {
                maxStep += resultSet.getInt(i);
            }
        }
        // 将结果塞回规则参数
        ruleParam.setUserActionSequenceQueriedMaxStep(ruleParam.getUserActionSequenceQueriedMaxStep() + maxStep);

        return maxStep == totalStep;
    }
}
